package edu.cmu.vlis.wassup.publisher;


import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.jms.JMSException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.sun.messaging.Topic;

import edu.cmu.vlis.wassup.db.Announcement;

/**
 * This class will continuously poll the Y! server to get stream of messages.
 */
public class UpcomingPoller extends AbstractPoller{

    Map <Integer,Topic> categoryMap;
    String baseURL;
    private static int id = 10000;

    public UpcomingPoller(){
        super(10000);
        this.categoryMap = new HashMap<Integer,Topic>();
        this.baseURL = System.getProperty("upcomingURL");
        this.getCategoryList();
    }

 
    public void getCategoryList() {
        //Initialize the categories
        StringBuilder queryURL = new StringBuilder(baseURL+"&method=category.getList");
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true); 
        DocumentBuilder builder = null;

        try {
            builder = domFactory.newDocumentBuilder();

        } catch (ParserConfigurationException e) {
            System.err.println("Parser is not configured properly.");
            e.printStackTrace();
        }

        Document doc = null;
        try {
            InputSource source = new InputSource(new URL(queryURL.toString()).openStream());
            source.setEncoding("UTF-8");  // Otherwise java may assume different encoding.
            doc = builder.parse(source); // Retrieving xml response and parsing it.
        } catch (SAXException e) {
            System.err.println("Got the response, but failed to parse.");
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("Failed to get the response. Check the internet connection");
            e.printStackTrace();
        }

        XPathFactory xpathFactory = XPathFactory.newInstance();
        XPath xpath = xpathFactory.newXPath();
        XPathExpression expr = null;
        try {
            // x-path expression used here finds all the events in the response
            expr = xpath.compile("//category");
        } catch (XPathExpressionException e) {
            System.err.println("Check the x-path expression. Probably its incorrect");
            e.printStackTrace();
        }
        NodeList categories = null;
        try {
            categories = (NodeList)expr.evaluate(doc, XPathConstants.NODESET); // Here the xpath query will be executed.
        } catch (XPathExpressionException e) {
            System.err.println("Check the x-path expression. Probably its incorrect");
            e.printStackTrace();
        }
        //Iterate thr all the categories and create a topic for each of them.
        for(int i=0; i< categories.getLength(); i++){
            NamedNodeMap map = categories.item(i).getAttributes();
            Node attrId = map.getNamedItem("id");
            Node attrTopic = map.getNamedItem("name");
            Integer catid = new Integer(attrId.getNodeValue());
            if(!this.categoryMap.containsKey(catid))
                try {
                    this.categoryMap.put(catid,new Topic(attrTopic.getNodeValue().trim().toLowerCase().replaceAll("[^a-z]", "")));
                } catch (DOMException e) {
                    e.printStackTrace();
                } catch (JMSException e) {
                    System.err.println("Failed to create topic for Upcoming poller for: "+attrTopic.getNodeValue());
                    e.printStackTrace();
                }
        }
    }

    public int getMessagesNputInPublisherQ(){
        StringBuilder queryURL = new StringBuilder(baseURL+"&method=event.search");
        String queryParams = System.getProperty("queryParams");
        if(queryParams != null)
            queryURL.append("&"+queryParams);
        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true); 
        DocumentBuilder builder = null;

        try {
            builder = domFactory.newDocumentBuilder();

        } catch (ParserConfigurationException e) {
            System.err.println("Parser is not configured properly.");
            e.printStackTrace();
        }
        Document doc = null;
        try {
            InputSource source = new InputSource(new URL(queryURL.toString()).openStream());
            source.setEncoding("UTF-8");  // Otherwise java may assume different encoding.
            doc = builder.parse(source); // Retrieving xml response and parsing it.
        } catch (SAXException e) {
            System.err.println("Got the response, but failed to parse.");
            e.printStackTrace();
        } catch (IOException e) {
            System.err.println("Failed to get the response. Check the internet connection");
            e.printStackTrace();
        }

        XPathFactory xpathFactory = XPathFactory.newInstance();
        XPath xpath = xpathFactory.newXPath();
        XPathExpression expr = null;
        try {
            // x-path expression used here finds all the events in the response
            expr = xpath.compile("//event");
        } catch (XPathExpressionException e) {
            System.err.println("Check the x-path expression. Probably its incorrect");
            e.printStackTrace();
        }
        NodeList events = null;
        try {
            events = (NodeList)expr.evaluate(doc, XPathConstants.NODESET); // Here the xpath query will be executed.
        } catch (XPathExpressionException e) {
            System.err.println("Check the x-path expression. Probably its incorrect");
            e.printStackTrace();
        }

        for(int i=0; i< events.getLength(); i++){
            Topic topic = null;
            NamedNodeMap map = events.item(i).getAttributes();
            try {
                Announcement ann = new Announcement("");
                for(int j=0; j<map.getLength();j++){
                    Node attr = map.item(j);
                    if (attr.getNodeName().equalsIgnoreCase("venue_city"))
                        ann.setCity(attr.getNodeValue());
                    else if (attr.getNodeName().equalsIgnoreCase("name"))
                        ann.setEvent_name(attr.getNodeValue());
                    else if (attr.getNodeName().equalsIgnoreCase("start_date"))
                        ann.setStart_date(attr.getNodeValue());
                    else if(attr.getNodeName().equalsIgnoreCase("end_date"))
                        ann.setEnd_date(attr.getNodeValue());
                    else if (attr.getNodeName().equalsIgnoreCase("description"))
                        ann.setDescription(attr.getNodeValue());
                    else if(attr.getNodeName().equalsIgnoreCase("start_time"))
                        ann.setStart_time(attr.getNodeValue());
                    else if (attr.getNodeName().equalsIgnoreCase("end_time"))
                        ann.setEnd_time(attr.getNodeValue());
                    else if (attr.getNodeName().equalsIgnoreCase("latitude"))
                        ann.setLatitude(Float.parseFloat(attr.getNodeValue()));
                    else if(attr.getNodeName().equalsIgnoreCase("longitude"))
                        ann.setLongitude(Float.parseFloat(attr.getNodeValue()));
                    else if (attr.getNodeName().equalsIgnoreCase("venue_state_name"))
                        ann.setState(attr.getNodeValue());
                    else if (attr.getNodeName().equalsIgnoreCase("venue_address"))
                        ann.setStreet_address(attr.getNodeValue());
                    else if(attr.getNodeName().equalsIgnoreCase("url"))
                        ann.setURL(attr.getNodeValue());
                    else if(attr.getNodeName().equalsIgnoreCase("category_id")) 
                        topic = this.categoryMap.get(Integer.parseInt(attr.getNodeValue().toLowerCase()));
                }
                if(topic!=null )  {
                    ann.setSender(null);
                    this.topicPublisher.publish(topic,this.topicSession.createObjectMessage(ann));
                }
                else
                    System.err.println("No category found for this message.");

            } catch (JMSException e1) {
                e1.printStackTrace();
            } 

        }
        return events.getLength();
    }
@Override
    public void startPoller() {
        System.out.println("Poller " + id + " is starting ");
        super.startPoller();
    }
    @Override
    public String getPollerName() {
        return "Upcoming";
    }

    @Override
    public int getID() {
        // TODO Auto-generated method stub
        return id;
    }
}
